import { Request, Response, NextFunction } from 'express';
import Joi from 'joi';
import { ValidationError } from './errorHandler';

export interface ValidationSchema {
  body?: Joi.ObjectSchema;
  query?: Joi.ObjectSchema;
  params?: Joi.ObjectSchema;
  headers?: Joi.ObjectSchema;
}

export const validateRequest = (schema: ValidationSchema) => {
  return (req: Request, res: Response, next: NextFunction): void => {
    const errors: string[] = [];

    // 验证请求体
    if (schema.body) {
      const { error } = schema.body.validate(req.body, { abortEarly: false });
      if (error) {
        errors.push(...error.details.map(detail => detail.message));
      }
    }

    // 验证查询参数
    if (schema.query) {
      const { error } = schema.query.validate(req.query, { abortEarly: false });
      if (error) {
        errors.push(...error.details.map(detail => detail.message));
      }
    }

    // 验证路径参数
    if (schema.params) {
      const { error } = schema.params.validate(req.params, { abortEarly: false });
      if (error) {
        errors.push(...error.details.map(detail => detail.message));
      }
    }

    // 验证请求头
    if (schema.headers) {
      const { error } = schema.headers.validate(req.headers, { abortEarly: false });
      if (error) {
        errors.push(...error.details.map(detail => detail.message));
      }
    }

    if (errors.length > 0) {
      const error = new ValidationError(errors.join('; '));
      return next(error);
    }

    next();
  };
};

// 常用的验证模式
export const commonSchemas = {
  // UUID验证
  uuid: Joi.string().uuid().required(),
  
  // 分页参数
  pagination: Joi.object({
    page: Joi.number().integer().min(1).default(1),
    limit: Joi.number().integer().min(1).max(100).default(20)
  }),

  // 日期范围
  dateRange: Joi.object({
    start_date: Joi.date().iso().required(),
    end_date: Joi.date().iso().min(Joi.ref('start_date')).required()
  }),

  // 用户注册
  userRegistration: Joi.object({
    username: Joi.string().alphanum().min(3).max(20).required()
      .messages({
        'string.alphanum': '用户名只能包含字母和数字',
        'string.min': '用户名至少需要3个字符',
        'string.max': '用户名不能超过20个字符',
        'any.required': '用户名是必填项'
      }),
    phone: Joi.string().pattern(/^1[3-9]\d{9}$/).required()
      .messages({
        'string.pattern.base': '请输入有效的手机号',
        'any.required': '手机号是必填项'
      }),
    email: Joi.string().email().optional()
      .messages({
        'string.email': '请输入有效的邮箱地址'
      }),
    password: Joi.string().min(6).max(50).required()
      .messages({
        'string.min': '密码至少需要6个字符',
        'string.max': '密码不能超过50个字符',
        'any.required': '密码是必填项'
      })
  }),

  // 用户登录
  userLogin: Joi.object({
    username: Joi.string().required()
      .messages({
        'any.required': '用户名或手机号是必填项'
      }),
    password: Joi.string().required()
      .messages({
        'any.required': '密码是必填项'
      })
  }),

  // 用户资料更新
  userProfileUpdate: Joi.object({
    birth_date: Joi.date().max('now').optional()
      .messages({
        'date.max': '出生日期不能是未来日期'
      }),
    height: Joi.number().min(100).max(250).optional()
      .messages({
        'number.min': '身高不能小于100cm',
        'number.max': '身高不能大于250cm'
      }),
    weight: Joi.number().min(30).max(200).optional()
      .messages({
        'number.min': '体重不能小于30kg',
        'number.max': '体重不能大于200kg'
      }),
    gender: Joi.string().valid('male', 'female', 'other').optional()
      .messages({
        'any.only': '性别只能是male、female或other'
      }),
    timezone: Joi.string().optional(),
    preferences: Joi.object().optional()
  }),

  // 健康数据同步
  healthDataSync: Joi.object({
    record_date: Joi.date().iso().required()
      .messages({
        'any.required': '记录日期是必填项'
      }),
    steps: Joi.number().integer().min(0).max(100000).optional()
      .messages({
        'number.min': '步数不能为负数',
        'number.max': '步数不能超过100000'
      }),
    distance: Joi.number().min(0).max(1000).optional()
      .messages({
        'number.min': '距离不能为负数',
        'number.max': '距离不能超过1000km'
      }),
    calories: Joi.number().integer().min(0).max(10000).optional()
      .messages({
        'number.min': '卡路里不能为负数',
        'number.max': '卡路里不能超过10000'
      }),
    active_minutes: Joi.number().integer().min(0).max(1440).optional()
      .messages({
        'number.min': '活跃分钟数不能为负数',
        'number.max': '活跃分钟数不能超过1440分钟'
      }),
    heart_rate_data: Joi.array().items(
      Joi.number().integer().min(30).max(220)
    ).optional()
      .messages({
        'array.base': '心率数据必须是数组格式'
      }),
    stress_level: Joi.number().integer().min(1).max(100).optional()
      .messages({
        'number.min': '压力水平最小值为1',
        'number.max': '压力水平最大值为100'
      }),
    data_source: Joi.string().max(50).required()
      .messages({
        'any.required': '数据源是必填项'
      })
  }),

  // 睡眠数据同步
  sleepDataSync: Joi.object({
    sleep_date: Joi.date().iso().required(),
    bedtime: Joi.date().iso().required(),
    sleep_start: Joi.date().iso().required(),
    wake_time: Joi.date().iso().required(),
    get_up_time: Joi.date().iso().required(),
    total_duration: Joi.number().integer().min(0).max(1440).required()
      .messages({
        'number.min': '睡眠时长不能为负数',
        'number.max': '睡眠时长不能超过1440分钟'
      }),
    deep_sleep: Joi.number().integer().min(0).optional(),
    light_sleep: Joi.number().integer().min(0).optional(),
    rem_sleep: Joi.number().integer().min(0).optional(),
    awake_duration: Joi.number().integer().min(0).optional(),
    sleep_efficiency: Joi.number().min(0).max(100).optional(),
    sleep_score: Joi.number().integer().min(0).max(100).optional(),
    wake_up_count: Joi.number().integer().min(0).optional(),
    sleep_stages: Joi.array().optional(),
    data_source: Joi.string().max(50).required()
  }),

  // LLM配置
  llmConfiguration: Joi.object({
    provider: Joi.string().valid('qwen', 'deepseek', 'private').required()
      .messages({
        'any.only': 'LLM提供商只能是qwen、deepseek或private',
        'any.required': 'LLM提供商是必填项'
      }),
    api_key: Joi.string().min(10).required()
      .messages({
        'string.min': 'API密钥至少需要10个字符',
        'any.required': 'API密钥是必填项'
      }),
    endpoint_url: Joi.string().uri().optional().allow('')
      .messages({
        'string.uri': '端点URL格式无效'
      }),
    model_config: Joi.object().optional()
  }),

  // 分析请求
  analysisRequest: Joi.object({
    analysis_type: Joi.string().valid('sleep', 'stress', 'exercise', 'general', 'nutrition').required()
      .messages({
        'any.only': '分析类型只能是sleep、stress、exercise、general或nutrition',
        'any.required': '分析类型是必填项'
      }),
    date_range: Joi.object({
      start_date: Joi.date().iso().required(),
      end_date: Joi.date().iso().min(Joi.ref('start_date')).required()
    }).required(),
    include_recommendations: Joi.boolean().optional()
  })
};

// 文件上传验证
export const validateFileUpload = (options: {
  allowedMimeTypes?: string[];
  maxFileSize?: number; // bytes
  required?: boolean;
}) => {
  return (req: Request, res: Response, next: NextFunction): void => {
    const file = req.file;
    
    if (options.required && !file) {
      return next(new ValidationError('文件是必需的'));
    }

    if (!file) {
      return next();
    }

    // 检查文件类型
    if (options.allowedMimeTypes && !options.allowedMimeTypes.includes(file.mimetype)) {
      return next(new ValidationError(`不支持的文件类型: ${file.mimetype}`));
    }

    // 检查文件大小
    if (options.maxFileSize && file.size > options.maxFileSize) {
      const maxSizeMB = (options.maxFileSize / (1024 * 1024)).toFixed(2);
      return next(new ValidationError(`文件大小不能超过${maxSizeMB}MB`));
    }

    next();
  };
};